import { createUniqueId } from '../use/createUniqueId.js';

/**
 * 初始化表头
 * 添加默认id确定最后一个flex
 * @param columns
 */
function initColumns(columns) {
  let maxFixedLeft = -1;
  let minFixedRight = Number.MAX_VALUE;
  const cols = [];
  getFlatColumns(columns, cols, undefined);
  let maxLevel = 1;
  const calculateSpans = (columns, parent) => {
    let colspan = 0;
    columns.forEach(col => {
      if (parent) {
        col._level = parent._level + 1;
        if (maxLevel < col._level) {
          maxLevel = col._level;
        }
      }
      if (col.children) {
        const cspan = calculateSpans(col.children, col);
        colspan += cspan;
        col._colspan = cspan;
      } else {
        col._colspan = 1;
        colspan += 1;
      }
    });
    return colspan;
  };
  columns.forEach(column => {
    column._level = 1;
  });
  calculateSpans(columns, undefined);
  // 构建rows
  const rows = [];
  for (let i = 0; i < maxLevel; i++) {
    rows.push([]);
  }
  const allColumns = getAllColumns(columns);
  allColumns.forEach(column => {
    if (!column.children) {
      column._rowspan = maxLevel - column._level + 1;
    } else {
      column._rowspan = 1;
    }
    rows[column._level - 1].push(column);
  });
  if (cols) {
    cols.forEach((col, index) => {
      col.id = col.id ?? createUniqueId();
      if (col.fixed === 'left') {
        maxFixedLeft = Math.max(maxFixedLeft, index);
      }
      if (col.fixed === 'right') {
        minFixedRight = Math.min(minFixedRight, index);
      }
    });
    if (maxFixedLeft > -1) {
      cols[maxFixedLeft] ? cols[maxFixedLeft].fixedLeftLast = true : void 0;
    }
    if (minFixedRight < Number.MAX_VALUE) {
      cols[minFixedRight] ? cols[minFixedRight].fixedRightFirst = true : void 0;
    }
  }
  return {
    maxFixedLeft,
    minFixedRight,
    columnsRows: rows,
    calcColumns: cols
  };
}

/**
 * 滚动条滚动后更新固定列的样式
 */
function updateScrollFixed(maxFixedLeft, minFixedRight, store, scrollLeft, clientWidth, scrollWidth) {
  if (maxFixedLeft >= 0 || minFixedRight < Number.MAX_VALUE) {
    store.showFixedLeft = scrollLeft > 0;
    store.showFixedRight = clientWidth + scrollLeft < scrollWidth;
  }
}

/**
 * 初始化表格数据
 * @param data
 */
function initData(data, rowKey) {
  let ret = data ?? [];
  ret = [...ret];
  ret.forEach((item, index) => {
    item.id = item[rowKey] ?? createUniqueId();
    item._originSort = index;
  });
  ret = buildTreeData(data);
  return ret;
}
function sortData(store, column) {
  const arr = [...store.data];
  if (column.sortType === '') {
    arr.sort((a, b) => {
      return a._originSort - b._originSort > 0 ? 1 : -1;
    });
  } else {
    if (column.sortMethod && typeof column.sortMethod === 'function') {
      arr.sort(column.sortMethod);
    } else {
      arr.sort((a, b) => {
        const name = column.name ?? '';
        if (/^[0-9\\.]+$/g.test(a[name])) {
          return (column.sortType === 'asc' ? 1 : -1) * (a[name] - b[name]) > 0 ? 1 : -1;
        } else {
          return (column.sortType === 'asc' ? 1 : -1) * a[name].localeCompare(b[name]);
        }
      });
    }
  }
  store.data = arr;
}
function _buildTreeData(data, target, level, show) {
  data.forEach(item => {
    item.id = item.id ?? createUniqueId();
    item._level = level;
    item._show = show;
    target.push(item);
    if (item.children && item.children.length) {
      _buildTreeData(item.children, target, level + 1, !!item._showChildren);
    }
  });
}

/**
 * 树形数据重构
 * @param data
 * @returns
 */
function buildTreeData(data) {
  const arr = [];
  _buildTreeData(data, arr, 0, true);
  return arr;
}
const hideChildren = (map, id) => {
  if (map[id] && map[id].children) {
    map[id].children.forEach(child => {
      child._show = false;
      hideChildren(map, child.id);
    });
  }
};
const showChildren = (map, id) => {
  const row = map[id];
  if (row && row.children) {
    row.children.forEach(child => {
      child._show = row._showChildren;
      hideChildren(map, child.id);
    });
  }
};

/**
 * 显示隐藏树形数据
 * @param setStore
 * @param row
 */
function showHideChildren(store, row) {
  store.data.forEach(item => {
    if (item.id === row.id) {
      item._showChildren = !item._showChildren;
    }
  });
  const ids = row.children.map(child => {
    return child.id;
  });
  const map = {};
  store.data.forEach(child => {
    map[child.id] = child;
  });
  ids.forEach(id => {
    if (map[id]) {
      map[id]._show = row._showChildren;
    }
    if (row._showChildren) {
      showChildren(map, id);
    } else {
      hideChildren(map, id);
    }
  });
}

/**
 * 排序信息
 * @param setStore
 * @param column
 * @param sortType
 */
function sortHandler(store, column, sortType) {
  store.columns.forEach(col => {
    if (col.name === column.name) {
      if (col.sortType === sortType) {
        col.sortType = '';
      } else {
        col.sortType = sortType;
      }
    }
  });

  // 远程排序的话使用custom
  if (column.sort !== 'custom') {
    sortData(store, column);
  }
}

/**
 * 添加或删除展开收缩的数据
 * @param setStore
 * @param column
 * @param row
 */
function addRemoveExpand(store, column, row) {
  let currentIndex = -1;
  const currentRow = store.data.find((item, index) => {
    const flag = item.id === row.id;
    if (flag) {
      currentIndex = index;
    }
    return flag;
  });

  // 关闭的时候进行打开,并设置_expand属性
  if (!currentRow._expand) {
    currentRow._expand = true;
    store.data.splice(currentIndex + 1, 0, {
      _type: 'expandChildren',
      _show: true,
      column,
      render: column.render?.bind(null, row)
    });
  } else {
    store.data.splice(currentIndex + 1, 1);
    currentRow._expand = false;
  }
}

// resize开始
const onResizeStart = (store, column, e) => {
  if (typeof e.button === 'number' && e.button !== 0) return false;
  store.resizing = true;
  const r = e.target.getBoundingClientRect().right;
  const l = e.target.closest('.cm-table-wrap').getBoundingClientRect().left;
  store.posX = r - l;
  store.startX = r - l;
  store.x = e.clientX;
  store.resizeId = column.id;
};

// resize鼠标移动
const onResizeMove = (store, e) => {
  if (store.resizing) {
    const deltaX = e.clientX - store.x;
    store.x = e.clientX;
    const posX = store.posX + deltaX;
    store.posX = posX;
  }
};
// resize结束
const onResizeEnd = (store, wrap) => {
  store.resizing = false;
  store.columns.filter(col => {
    if (col.id === store.resizeId) {
      let w = col.width ? parseFloat(col.width) + (store.posX - store.startX) : undefined;
      if (w && col.minWidth) {
        w = Math.max(w, col.minWidth);
      }
      if (w && col.maxWidth) {
        w = Math.min(w, col.maxWidth);
      }
      col.width = w ? w + 'px' : undefined;
    }
  });
  observerSizeChange(store, wrap);
  let nextId;
  store.columns.find((col, index) => {
    const flag = col.id === store.resizeId;
    if (flag) {
      nextId = store.columns[index + 1] ? store.columns[index + 1].id : undefined;
    }
    return flag;
  });
  store.columns.filter(col => col.id === nextId).forEach(col => col._ = createUniqueId());
  store.posX = 0;
};
const observerSizeChange = (store, wrap) => {
  let wrapWidth = wrap.querySelector('.cm-table').getBoundingClientRect().width;
  const body = wrap.querySelector('.cm-table-body');
  const hasScroll = body.offsetHeight < body.scrollHeight;
  if (hasScroll) {
    const scrollWidth = body.offsetWidth - body.clientWidth;
    wrapWidth -= scrollWidth;
  }
  const fxiedWidthColumns = store.columns.filter(col => col.width);
  const fixedWidth = fxiedWidthColumns.reduce((pre, cur) => pre + (cur.width ? parseFloat(cur.width) : 0), 0);
  const dynamicWidthColumns = store.columns.filter(col => !col.width);
  if (dynamicWidthColumns.length > 0) {
    const allDynamicWidth = Math.max(wrapWidth - fixedWidth, 0);
    const dynamicWidth = allDynamicWidth / dynamicWidthColumns.length;
    let remainWidth = allDynamicWidth;
    // 先设置有minWidth或maxWidth的列
    dynamicWidthColumns.filter(col => col.minWidth || col.maxWidth).forEach(col => {
      let w = dynamicWidth;
      if (col.minWidth) {
        w = Math.max(w, col.minWidth);
      }
      if (col.maxWidth) {
        w = Math.min(w, col.maxWidth);
      }
      remainWidth -= w;
      col._width = w;
    });
    const remianColumns = dynamicWidthColumns.filter(col => !(col.minWidth || col.maxWidth));
    const remainColWidth = remainWidth / remianColumns.length;
    remianColumns.forEach(col => {
      col._width = remainColWidth;
    });
  }
  fxiedWidthColumns.forEach(col => {
    const w = col.width ? parseFloat(col.width) : 0;
    store.columns.filter(c => col.id === c.id).forEach(col => {
      col._width = w;
    });
  });
};

/**
 * 获取占用宽度的列
 * @param columns 列
 * @param flatColumns
 * @returns
 */
const getFlatColumns = (columns, flatColumns = [], parent) => {
  columns.forEach(col => {
    col.id = col.id ?? createUniqueId();
    if (!col.name) {
      col.name = col.id;
    }
    col._parent = parent;
    if (col.children) {
      getFlatColumns(col.children, flatColumns, col);
    } else {
      flatColumns.push(col);
    }
  });
};
const getAllColumns = columns => {
  return columns.flatMap(col => {
    if (col.children) {
      return [col, ...getAllColumns(col.children)];
    } else {
      return [col];
    }
  });
};

export { _buildTreeData, addRemoveExpand, buildTreeData, getAllColumns, getFlatColumns, initColumns, initData, observerSizeChange, onResizeEnd, onResizeMove, onResizeStart, showHideChildren, sortData, sortHandler, updateScrollFixed };
